home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 10 - 1994 / 10.10 Oct 94 / Sprocket / Lib / AppLib.cp < prev    next >
Encoding:
Text File  |  1994-08-27  |  11.3 KB  |  522 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        AppLib.cp
  3.  
  4.     Contains:    The “guts” of a Macintosh application.
  5.  
  6.     Written by: Dave Falkenburg and many other SmartFriends™
  7.  
  8.     Copyright:    © 1993-94 by Dave Falkenburg, all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.      
  12.  */
  13.  
  14. #ifdef    SystemSevenOrLater
  15. #undef    SystemSevenOrLater
  16. #endif
  17. #define    SystemSevenOrLater    1
  18.  
  19. #include <limits.h>        //    For LONG_MAX
  20.  
  21. #include <Types.h>
  22. #include <Quickdraw.h>
  23. #include <Fonts.h>
  24. #include <Menus.h>
  25. #include <Windows.h>
  26. #include <Dialogs.h>
  27. #include <Desk.h>
  28. #include <Events.h>
  29. #include <AppleEvents.h>
  30. #include <DiskInit.h>
  31.  
  32. #if qUseETO15Interfaces
  33. #include <Gestalt.h>
  34. #include <CodeFragments.h>
  35. #include <Devices.h>
  36. #else
  37. #include <GestaltEqu.h>
  38. #include <FragLoad.h>
  39. #endif
  40.  
  41. #include <ToolUtils.h>
  42. #include <Traps.h>
  43. #include <LowMem.h>
  44.  
  45. #include <Threads.h>
  46. #include <Drag.h>
  47. #include <Editions.h>
  48. #include <OCEStandardMail.h>
  49.  
  50. #if    qInlineInputAware
  51. #include <TextServices.h>
  52. #include <TSMTE.h>
  53. #endif
  54.  
  55. #include "AppLib.h"
  56. #include "StandardMenus.h"
  57. #include "Window.h"
  58. #include "SplashWindow.h"
  59. #include "MailableWindow.h"
  60. #include "AppleEventHandling.h"
  61.  
  62. #if    qUseQuickDrawGX
  63. #include <graphics macintosh.h>
  64. #include <graphics routines.h>
  65. #include <PrintingManager.h>
  66. #endif
  67.  
  68.  
  69. //    Function Prototypes
  70.  
  71. void    main(void);
  72. void    MainEventLoop(void);
  73.  
  74. void    HandleMouseDown(TWindow * topWindowObj, EventRecord * anEvent);
  75. void    HandleUpdate(EventRecord * anEvent);
  76. void    HandleClose(WindowPtr aWindow);
  77.  
  78.  
  79. //    Globals
  80.  
  81. Boolean                gDone = false;
  82. Boolean                gMenuBarNeedsUpdate = true;
  83.  
  84. Boolean                gHasColorQuickdraw = false;
  85. Boolean                gHasThreadManager = false;
  86. Boolean                gHasDragManager = false;
  87. Boolean                gHasAppleScript = false;
  88. Boolean                gHasAOCE = false;
  89. Boolean                gHasDisplayManager = false;
  90.  
  91. GrafPtr                gWindowManagerPort;
  92. Rect                gDeskRectangle;
  93. RgnHandle            gMouseRegion = nil;
  94.  
  95. short                gPreferencesRsrcRefNum;
  96.  
  97. #if    qInlineInputAware
  98. Boolean                gHasTextServices = false;
  99. Boolean                gHasTSMTE = false;
  100. #endif
  101.  
  102. #if    qUseQuickDrawGX
  103. Boolean                gHasQuickDrawGX = false;
  104. long                gQuickDrawGXVersion = 0;
  105. long                gQuickDrawGXPrintingVersion = 0;
  106. gxGraphicsClient    gQuickDrawGXClient;
  107.  
  108.  
  109. //    PrintingEventOverride is our generic event handler for QuickDrawGX.
  110. //    It alows us to handle events while the QuickDrawGX movable modal
  111. //    printing dialogs are displayed.
  112.  
  113. //    ¿ Really should move to a GX-specific place ?
  114.  
  115. OSErr
  116. PrintingEventOverrideForGX(EventRecord *anEvent, Boolean filterEvent)
  117.     {
  118.     if (!filterEvent)
  119.         switch (anEvent->what)
  120.             {
  121.             case mouseDown:
  122.             case keyDown:
  123.             case autoKey:
  124.                 break;
  125.  
  126.             default:
  127.                 HandleEvent(anEvent);
  128.             }
  129.  
  130.     return noErr;
  131.     }
  132.  
  133. #endif
  134.  
  135.  
  136. //    Values that can be adjusted by other application code to change
  137. //    the behavior of the MainEventLoop.
  138. //
  139. //    Rules of thumb:
  140. //
  141. //        Increase gXXXRunQuantum (and decrease gXXXSleepQuantum) when:
  142. //            The application has many threads running that need time
  143. //
  144. //        Decrease gXXXRunQuantum when:
  145. //            Sending AppleEvents to other applications
  146. //            Launching other applications
  147. //            Running in the background
  148.  
  149. unsigned long    gForegroundRunQuantum = 0;
  150. unsigned long    gForegroundSleepQuantum = GetCaretTime();
  151. unsigned long    gBackgroundRunQuantum = 0;
  152. unsigned long    gBackgroundSleepQuantum = LONG_MAX;
  153.  
  154.  
  155. //    Globals used to “tune” the performance of MainEventLoop
  156. //    (assume we’ll be starting in the foreground)
  157.  
  158. static    unsigned long    gRunQuantum = gForegroundRunQuantum;
  159. static    unsigned long    gSleepQuantum = gForegroundSleepQuantum;
  160.  
  161. #ifdef    powerc
  162. #ifndef    __MWERKS__
  163. QDGlobals    qd;
  164. #endif
  165. #endif
  166.  
  167. void
  168. main(void)
  169.     {
  170.     long        feature;
  171.  
  172.     MaxApplZone();
  173.     MoreMasters();
  174.     MoreMasters();
  175.     MoreMasters();
  176.     MoreMasters();
  177.  
  178.     InitGraf(&qd.thePort);    
  179.     InitFonts();
  180.     InitWindows();
  181.     InitMenus();
  182.     TEInit();
  183.     InitDialogs(nil);
  184.  
  185.  
  186.     if (GetToolTrapAddress(_Unimplemented) == GetOSTrapAddress(_Gestalt))
  187.         FatalErrorAlert(kCoreErrorStrings,kUnsupportedSystemSoftware);
  188.  
  189.     if (Gestalt(gestaltQuickdrawFeatures,&feature) == noErr)
  190.         gHasColorQuickdraw = ((feature & (1 << gestaltHasColor)) != 0);
  191.  
  192.     
  193.     TSplashWindow * splashWindow = new TSplashWindow;
  194.     
  195.     
  196.     if ((Gestalt(gestaltAppleEventsAttr,&feature) == noErr) &&
  197.         (feature & (1 << gestaltAppleEventsPresent)))
  198.         {
  199.         //    Figure out if we need to do AppleEvent recording
  200.         gHasAppleScript = (feature & (1 << gestaltScriptingSupport));
  201.         }
  202.     else
  203.         FatalErrorAlert(kCoreErrorStrings,kUnsupportedSystemSoftware);
  204.  
  205. #if    qInlineInputAware
  206.     if ((Gestalt(gestaltTSMgrVersion,&feature) == noErr) && (feature >= 1))
  207.         {
  208.         gHasTextServices = true;
  209.         if (Gestalt(gestaltTSMTEAttr, &feature) == noErr)
  210.             gHasTSMTE = (feature & (1 << gestaltTSMTEPresent));
  211.         }
  212. #endif
  213.  
  214.     if (Gestalt(gestaltThreadMgrAttr,&feature) == noErr)
  215.         {
  216. #ifdef    powerc
  217.         //    If running on a PowerPC, make sure that we not only have the
  218.         //    68K Thread Manager, but also the PowerPC shared library, too.
  219.         //    Because of the wonders of weak linking and out of memory errors
  220.         //    we need to also check to make sure that an entrypoint in the library
  221.         //    is there, too. 
  222.         if ((Ptr) NewThread != kUnresolvedSymbolAddress)
  223.             gHasThreadManager = ((feature & ((1 << gestaltThreadMgrPresent) | (1 << gestaltThreadsLibraryPresent))) != 0);
  224. #else
  225.         gHasThreadManager = ((feature & (1 << gestaltThreadMgrPresent)) != 0);
  226. #endif
  227.         }
  228.         
  229.     //    Check for and install Drag Manager callbacks
  230.     if (Gestalt(gestaltDragMgrAttr,&feature) == noErr)
  231.         {
  232. #ifdef    powerc
  233.         //    If running on a PowerPC, make sure that we not only have the
  234.         //    68K Drag Manager, but also the PowerPC shared library, too.
  235.         if ((Ptr) NewDrag != kUnresolvedSymbolAddress)
  236.             gHasDragManager = ((feature & ((1 << gestaltDragMgrPresent) | (1 << gestaltPPCDragLibPresent))) != 0);
  237. #else
  238.         gHasDragManager = ((feature & (1 << gestaltDragMgrPresent)) != 0);
  239. #endif
  240.  
  241.         if (gHasDragManager)
  242.             {
  243.             InstallTrackingHandler(NewDragTrackingHandlerProc(CallWindowDragTrackingHandler),(WindowPtr) nil,nil);
  244.             InstallReceiveHandler(NewDragReceiveHandlerProc(CallWindowDragReceiveHandler),(WindowPtr) nil,nil);
  245.             }
  246.         }
  247.  
  248.     //    Check for Display Manager
  249.     if (Gestalt(gestaltDisplayMgrAttr,&feature) == noErr)
  250.         gHasDisplayManager = ((feature & (1 << gestaltDisplayMgrPresent)) != 0);
  251.     
  252.     //    Check for and initialize AOCE Standard Mail package if it exists
  253.     if ((Gestalt(gestaltSMPMailerVersion,&feature) == noErr) && (feature != 0))
  254.         {
  255. #ifdef    powerc
  256.         if ((Ptr) SMPInitMailer != kUnresolvedSymbolAddress)
  257.             gHasAOCE = (SMPInitMailer(kSMPVersion) == noErr);
  258. #else
  259.         gHasAOCE = (SMPInitMailer(kSMPVersion) == noErr);
  260. #endif
  261.         }
  262.  
  263. #if    qUseQuickDrawGX
  264.     //    Check for and initialize QuickDrawGX
  265.     if (Gestalt(gestaltGXVersion, &gQuickDrawGXVersion) == noErr)
  266.         if (Gestalt(gestaltGXPrintingMgrVersion,&gQuickDrawGXPrintingVersion) == noErr)
  267. #ifdef    powerc
  268.             if ((Ptr) GXEnterGraphics != kUnresolvedSymbolAddress)
  269.                 gHasQuickDrawGX = true;
  270. #else
  271.             gHasQuickDrawGX = true;
  272. #endif
  273.  
  274.     if (gHasQuickDrawGX)
  275.         {
  276. //        gQuickDrawGXClient = GXNewGraphicsClient(nil, kGraphicsHeapSize, (gxClientAttribute) 0);
  277.         GXEnterGraphics();
  278.         GXInitPrinting();
  279.         }
  280. #endif
  281.         
  282.     //    Install our AppleEvent Handlers
  283.     InstallAppleEventHandlers();
  284.  
  285.     //    Setup desktop rectangle for dragging windows around            
  286.     GetWMgrPort(&gWindowManagerPort);
  287.     gDeskRectangle = (**GetGrayRgn()).rgnBBox;
  288.  
  289.     //    Get the default menubar
  290.     SetMenuBar(GetNewMBar(rMenuBar));
  291.     AddResMenu(GetMHandle(mApple),'DRVR');
  292.     
  293.     gPreferencesRsrcRefNum = OpenPreferencesResFile();
  294.     
  295.     if (SetupApplication() == noErr)
  296.         {
  297.         delete    splashWindow;    //    get rid of the splash screen
  298.         MainEventLoop();
  299.         TearDownApplication();
  300.         }
  301.         
  302. #if    qUseQuickDrawGX
  303.     if (gHasQuickDrawGX)        //    Tear down QuickDrawGX
  304.         {
  305.         GXExitPrinting();
  306. //        GXDisposeGraphicsClient(gQuickDrawGXClient);    //    DIES A HORRIBLE DEATH FOR ME?
  307.         GXExitGraphics();
  308.         }
  309. #endif
  310.     }
  311.  
  312.  
  313. void
  314. MainEventLoop(void)
  315.     {
  316.     EventRecord        anEvent;
  317.     unsigned long    nextTimeToCheckForEvents = 0;
  318.     
  319.     while (!gDone)
  320.         {
  321.         if (gMenuBarNeedsUpdate)
  322.             {
  323.             gMenuBarNeedsUpdate = false;
  324.             DrawMenuBar();
  325.             }
  326.             
  327.         if ((gRunQuantum == 0) ||
  328.             (TickCount() > nextTimeToCheckForEvents))
  329.             {
  330.             nextTimeToCheckForEvents = TickCount() + gRunQuantum;
  331.             
  332.             (void) WaitNextEvent(everyEvent,&anEvent,gSleepQuantum,gMouseRegion);
  333.                         
  334.             HandleEvent(&anEvent);
  335.             }
  336.  
  337.         if (gHasThreadManager)
  338.             YieldToAnyThread();
  339.         }
  340.     }
  341.  
  342.  
  343. void
  344. HandleEvent(EventRecord *anEvent)
  345.     {
  346.     TWindow    * wobj;
  347.     
  348.     if (anEvent->what != updateEvt)
  349.         wobj = GetWindowObject(FrontNonFloatingWindow());
  350.     else
  351.         wobj = GetWindowObject((WindowPtr) anEvent->message);
  352.  
  353.     if (wobj != nil)
  354.         wobj->AdjustCursor(anEvent);
  355.     
  356.     if ((wobj != nil) && wobj->EventFilter(anEvent))
  357.         return;
  358.         
  359.     else switch (anEvent->what)
  360.         {
  361.         case    nullEvent:
  362.             if (wobj != nil)
  363.                 wobj->Idle(anEvent);
  364.             break;
  365.             
  366.         case    mouseDown:
  367.             HandleMouseDown(wobj,anEvent);
  368.             break;
  369.         
  370.         case    keyDown:
  371.         case    autoKey:
  372.             if (anEvent->modifiers & cmdKey)
  373.                 HandleMenu(wobj,MenuKey((short) anEvent->message & charCodeMask));
  374.             else if (wobj != nil)
  375.                 wobj->KeyDown(anEvent);
  376.             break;
  377.             
  378.         case    updateEvt:
  379.             HandleUpdate(anEvent);
  380.             break;
  381.             
  382.         case diskEvt:
  383.             if (anEvent->message >> 16)
  384.                 {
  385.                 static    Point    where = {50,50};
  386.                 (void) DIBadMount(where,anEvent->message);
  387.                 }
  388.             break;
  389.                 
  390.         case    osEvt:
  391.             switch ((anEvent->message & osEvtMessageMask) >> 24)
  392.                 {
  393.                 case    mouseMovedMessage:
  394.                     break;
  395.                     
  396.                 case    suspendResumeMessage:                    
  397.                     if (anEvent->message & resumeFlag)
  398.                         {
  399.                         gRunQuantum = gForegroundRunQuantum;
  400.                         gSleepQuantum = gForegroundSleepQuantum;
  401.                         }
  402.                     else
  403.                         {
  404.                         gRunQuantum = gBackgroundRunQuantum;
  405.                         gSleepQuantum = gBackgroundSleepQuantum;
  406.                         }
  407.  
  408.                     SuspendResumeWindows((anEvent->message & resumeFlag) != 0);
  409.                     if (anEvent->message & convertClipboardFlag)
  410.                         ConvertClipboard();
  411.                     break;
  412.                 }
  413.             break;
  414.         
  415.         case    kHighLevelEvent:
  416.             (void) AEProcessAppleEvent(anEvent);
  417.             break;
  418.             
  419.         default:
  420.             break;
  421.         }
  422.     }
  423.  
  424. void
  425. HandleMouseDown(TWindow * topWindowObj,EventRecord *anEvent)
  426.     {
  427.     WindowPtr    aWindow;
  428.     short        partCode;
  429.     TWindow        *wobj;
  430.  
  431.     partCode = FindWindow(anEvent->where,&aWindow);
  432.     wobj = GetWindowObject(aWindow);
  433.     switch(partCode)
  434.         {
  435.         case    inMenuBar:
  436.             HandleMenu(topWindowObj,MenuSelect(anEvent->where));
  437.             break;
  438.             
  439.         case    inSysWindow:
  440.             SystemClick(anEvent,aWindow);
  441.             break;
  442.             
  443.         case    inContent:
  444.             if (wobj)
  445.                 {
  446.                 GrafPtr    oldPort;
  447.                 
  448.                 GetPort(&oldPort);
  449.                 SetPort(aWindow);
  450.                 GlobalToLocal(&anEvent->where);
  451.                 wobj->Click(anEvent);
  452.                 SetPort(aWindow);
  453.                 }
  454.             break;
  455.             
  456.         case    inDrag:
  457.             if (wobj)
  458.                 wobj->Drag(anEvent->where);
  459.             break;
  460.             
  461.         case    inGrow:
  462.             if (wobj)
  463.                 wobj->Grow(anEvent->where);
  464.             break;
  465.             
  466.         case    inGoAway:
  467.             if (TrackGoAway(aWindow,anEvent->where))
  468.                 HandleClose(aWindow);
  469.             break;
  470.  
  471.         case    inZoomIn:
  472.         case    inZoomOut:
  473.             if (TrackBox(aWindow,anEvent->where,partCode) && (wobj))
  474.                 wobj->Zoom(partCode);
  475.             break;
  476.             
  477.         default:
  478.             break;
  479.         }
  480.     }
  481.     
  482.  
  483. void    HandleUpdate(EventRecord * anEvent)
  484.     {
  485.     GrafPtr        oldPort;
  486.     WindowPtr    aWindow = (WindowPtr) anEvent->message;    
  487.     TWindow    *    wobj;
  488.         
  489.     GetPort(&oldPort);
  490.     SetPort(aWindow);
  491.     BeginUpdate(aWindow);
  492.     
  493.     if ((wobj = GetWindowObject(aWindow)) != nil)
  494.         wobj->Draw();
  495.     
  496.     EndUpdate(aWindow);
  497.     SetPort(oldPort);
  498.     }
  499.  
  500. void
  501. HandleClose(WindowPtr aWindow)
  502.     {
  503.     short    windowKind;
  504.     TWindow    *wobj;
  505.     
  506.     if (aWindow)
  507.         {
  508.         windowKind = ((WindowPeek) aWindow)->windowKind;
  509.         if (windowKind < 0)
  510.             {
  511.             CloseDeskAcc(((WindowPeek)aWindow)->windowKind);
  512.             }
  513.         else if ( ((wobj = GetWindowObject(aWindow)) != nil) &&
  514.                     wobj->CanClose() &&
  515.                     wobj->Close() &&
  516.                     wobj->DeleteAfterClose())
  517.             {
  518.             delete wobj;
  519.             }
  520.         }
  521.     }
  522.